package model.tokens;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import state.TabState;

import model.expression.AbstractExpression;
import model.expression.VariableExpression;
import model.parser.Parser;
import model.parser.ParserException;
import model.parser.ParsingData;


import expression.*;

/**
 * model.tokens that has a value and doesn't operate 
 * 
 * @author KevinWang Chris James Misha Lavrov
 *
 * @param <T>
 */
public class VariableToken extends AbstractToken 
{
    public String myValue;
    
    public VariableToken(String value,ParsingData parsingData)
    {
    	
        myValue = value;
    }

	@Override
	public void convertToPostFix(Stack<AbstractToken> opStack,
			Stack<AbstractExpression> outStack,TabState tabSt,Stack<AbstractExpression> out) throws ParserException
	{
			outStack.push(new VariableExpression(myValue,tabSt));
	}
	
	@Override
	public Stack<AbstractExpression> makeExpression(List<AbstractToken> toks,
			Stack<AbstractExpression> out, TabState ts,Parser parser)throws ParserException{

		Stack<AbstractExpression> outStack = new Stack<AbstractExpression>();
		AbstractExpression exp;
		
		//the variable already exists
		if(ts.variables.containsKey(this.myValue)){
			exp= new VariableExpression(myValue,ts);
			outStack.add(exp);
			return outStack;
		}else{ //
			//we need to make the variable expression
			if (toks.size()==1 || 
					!(toks.get(1) instanceof AssignmentToken)){
				//var not defined by user
				throw new ParserException("Please define  variable "+ myValue); 
			}
				//create the expressions that the var corresponds to
				outStack=toks.get(1).makeExpression(toks.subList(2,toks.size()), out, ts,parser);
				
				//variables need to be parsed out in the future as if they were commands.
				parser.commandRegEx+="|(?<=("+this.myValue+"))|(?=("+this.myValue+"))";
				
				ArrayList<AbstractExpression> list = new ArrayList<AbstractExpression>(outStack);
				ts.addVars(myValue, list);
				
				//tell the controller to update with a new variable value
				ts.notifyObservers("VariableUpdate "+myValue);
		}
		return outStack;
		
	}
}
